#include "imageloader.h"
#include "ui_imageloader.h"

#ifndef QT_NO_CONCURRENT
const int THUMNAIL_SIZE = 97;        // Size of thumbnail

QImage loadImage(const QString &fileName)
{
    Mat img = imread(fileName.toStdString());
    if(!img.data) return QImage();
    Mat rgb;
    cvtColor(img, rgb, CV_BGR2RGB);

    QImage image = QImage(rgb.data, rgb.cols, rgb.rows, rgb.step, QImage::Format_RGB888);
    image = image.scaled(THUMNAIL_SIZE, THUMNAIL_SIZE, Qt::KeepAspectRatio, Qt::FastTransformation);

    return image;
}

ImageLoader::ImageLoader(QWidget *parent) :
    QDialog(parent),
    m_ui(new Ui::ImageLoader)
{
    m_ui->setupUi(this);
    m_ui->scrollAreaWidgetContents->setLayout(m_ui->horizontalLayout);
    m_ui->scrollArea->setAutoFillBackground(true);

    mapper = new QSignalMapper;

    loader = new QFutureWatcher<QImage>;

    theButton = 0;
    loadedFiles = 0;

    qRegisterMetaType<QImage>("QImage");

    bar = m_ui->scrollArea->horizontalScrollBar();
    bar->setMinimum(0);
    bar->setSliderPosition(0);
    bar->setSingleStep(100);
    bar->setPageStep(300);

    progress.setFixedWidth(350);
    progress.setLabelText("Loading experimental images...please wait");

    connect(m_ui->leftButton, SIGNAL(released()), this, SLOT(moveLeft()));
    connect(m_ui->leftButton, SIGNAL(pressed()), this, SLOT(slideLeft()));
    connect(m_ui->rightButton, SIGNAL(released()), this, SLOT(moveRight()));
    connect(m_ui->rightButton, SIGNAL(pressed()), this, SLOT(slideRight()));
    connect(mapper, SIGNAL(mapped(int)), this, SLOT(displayImage(int)));
    connect(loader, SIGNAL(resultReadyAt(int)), this, SLOT(addButton(int)));
    connect(loader, SIGNAL(finished()), this, SLOT(finished()));
    connect(loader, SIGNAL(progressRangeChanged(int,int)), &progress, SLOT(setRange(int,int)));
    connect(loader, SIGNAL(progressValueChanged(int)), &progress, SLOT(setValue(int)));
    connect(&progress, SIGNAL(canceled()), loader, SLOT(cancel()));
}

ImageLoader::~ImageLoader()
{
    if(theButton) delete theButton;

    buttonList.clear();

    loader->cancel();
    loader->waitForFinished();

    delete m_ui;
    delete loader;
    loader = 0;
}

void ImageLoader::changeEvent(QEvent *e)
{
    QDialog::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        m_ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void ImageLoader::reload()
{
    int count = files.size();

    if(count == 0)
        return;

    buttonList.clear();

    if(loader->isRunning())
    {
        loader->cancel();
        loader->waitForFinished();
    }

    for(int i = 0; i < count; i++)
    {
        QToolButton *click = new QToolButton;
        buttonList.append(click);
    }

    loader->setFuture(QtConcurrent::mapped(files, loadImage));
    progress.exec();
}

void ImageLoader::displayImage(int id)
{
    QString fileName = files.at(id);

    Mat temp = imread(fileName.toStdString());
    if(!temp.data) return;

    Mat rgb;
    cvtColor(temp, rgb, CV_BGR2RGB);

    QImage qTemp = QImage(rgb.data, rgb.cols, rgb.rows, rgb.step, QImage::Format_RGB888);
    if(qTemp.isNull()) return;
    else qTemp = qTemp.scaled(m_ui->imageLabel->size(), Qt::IgnoreAspectRatio);

    m_ui->imageLabel->setPixmap(QPixmap::fromImage(qTemp, 0));

    if(theButton) theButton->setStyleSheet("");
    theButton = buttonList[id];
    theButton->setStyleSheet("background-color: #dd9619;"
                          "border-width: 3px;");
    currFile = fileName;
    emit imageSelected(fileName);
}


void ImageLoader::addFiles(const QVector<QString>& files)
{
    this->files = files;
}

void ImageLoader::updateIcons(const QStringList& filter)
{
    for(int i = 0; i < files.size(); i++)
    {
        const QString file = files.at(i);
        bool contain = false;

        for(int j = 0; j < filter.size(); j++)
        {
            QString fil = filter.at(j);

            if(file.contains(fil))
            {
                contain = true;
            }
        }

        if(!contain)
        {
            files.remove(i);
            mapper->removeMappings(buttonList[i]);
            buttonList.removeAt(i);
        }
    }
}

// Once all the images have been loaded, then create tool buttons
// associated with each image
void ImageLoader::addButton(int id)
{
    QIcon icon;
    QImage image = loader->resultAt(id);
    if(!image.isNull())
    {
        QToolButton *click = buttonList.at(id);
        icon.addPixmap(QPixmap::fromImage(image, 0));
        click->setIconSize(icon.actualSize(QSize(THUMNAIL_SIZE, THUMNAIL_SIZE)));
        click->setIcon(icon);

        m_ui->horizontalLayout->addWidget(click);
        connect(click, SIGNAL(clicked()), mapper, SLOT(map()));
        mapper->setMapping(click, id);

        loadedFiles++;
    }
}

void ImageLoader::finished()
{
    progress.hide();
}

void ImageLoader::moveLeft()
{
    bar->triggerAction(QAbstractSlider::SliderPageStepSub);
}

void ImageLoader::slideLeft()
{
    bar->triggerAction(QAbstractSlider::SliderMove);
}

void ImageLoader::moveRight()
{
    bar->triggerAction(QAbstractSlider::SliderPageStepAdd);
}

void ImageLoader::slideRight()
{
    bar->triggerAction(QAbstractSlider::SliderMove);
}

void ImageLoader::addResultImg(const Mat &img)
{
    if(!img.data) return;

    QImage qTemp;

    Mat rgb;
    cvtColor(img, rgb, CV_BGR2RGB);

    uchar *data = rgb.data;
    int width = rgb.cols;
    int height = rgb.rows;
    int bytes = rgb.step;
    int chn = rgb.channels();

    if(chn == 1)
        qTemp = QImage(data, width, height, bytes, QImage::Format_Mono);
    else
        qTemp = QImage(data, width, height, bytes, QImage::Format_RGB888);

    if(qTemp.isNull()) return;
    else qTemp = qTemp.scaled(m_ui->imageLabel->size(), Qt::KeepAspectRatio);

    m_ui->imageLabel_2->setPixmap(QPixmap::fromImage(qTemp, 0));
}

// Clear imageloader's result image
void ImageLoader::clearDisplay()
{
    m_ui->imageLabel_2->setPixmap(QPixmap());
}

QString ImageLoader::getFileByIndex(int id)
{
    if(files.size() == 0)
        return "";
    return files.at(id);
}

QString ImageLoader::getCurrFile()
{
    if(currFile.length() == 0)
        return "";

    return currFile;
}

int ImageLoader::getCurrIndex()
{
    if(currFile.length() == 0)
        return -1;

    return files.indexOf(currFile);
}

#endif // QT_NO_CONCURRENT
